/**
 * @file test_sort.cpp
 * @author 逆流 (1171267147@qq.com)
 * @brief 测试STL的排序算法
 * @version 0.1
 * @date 2024-09-15
 *
 * @copyright Copyright (c) 2024
 *
 */
#include <gtest/gtest.h>

#include <algorithm>
#include <chrono>
#include <cstddef>
#include <cstdlib>
#include <random>
#include <vector>

struct MyType {
    int a;
    int b;
};

struct MyTypeWithCmp {
    int a;
    int b;

    bool operator<(const MyTypeWithCmp& other) const { return a < other.a; }
};

TEST(TestSort, DefaultType) {
    std::vector<int> nums = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

    auto seed = std::chrono::system_clock::now().time_since_epoch().count();

    std::shuffle(nums.begin(), nums.end(), std::default_random_engine(seed));

    EXPECT_FALSE(std::is_sorted(nums.begin(), nums.end()));

    std::sort(nums.begin(), nums.end());

    EXPECT_TRUE(std::is_sorted(nums.begin(), nums.end()));
}

TEST(TestSort, CustomType) {
    std::vector<MyType> nums(10);

    EXPECT_EQ(nums.size(), 10);

    auto cmp = [](const MyType& a, const MyType& b) {
        return a.a < b.a;
    };
    auto temp = std::chrono::system_clock::now().time_since_epoch().count();
    auto seed = static_cast<unsigned int>(temp);

    for (size_t i = 0; i < nums.size(); i++) {
        // !rand()可能存在线程安全问题，使用rand_r()替代
        // !rand_r()不允许传入nullptr
        nums[i].a = rand_r(&seed) % 100;
        nums[i].b = rand_r(&seed) % 200;
    }

    std::sort(nums.begin(), nums.end(), cmp);

    EXPECT_TRUE(std::is_sorted(nums.begin(), nums.end(), cmp));
}

TEST(TestSort, CustomTypeWithCmp) {
    std::vector<MyTypeWithCmp> nums(10);

    EXPECT_EQ(nums.size(), 10);

    auto temp = std::chrono::system_clock::now().time_since_epoch().count();
    auto seed = static_cast<unsigned int>(temp);

    for (size_t i = 0; i < nums.size(); i++) {
        nums[i].a = rand_r(&seed) % 100;
        nums[i].b = rand_r(&seed) % 200;
    }

    std::sort(nums.begin(), nums.end());

    EXPECT_TRUE(std::is_sorted(nums.begin(), nums.end()));
}
